package cn.demoncat.util.mongo.dao;

import java.io.InputStream;
import java.util.Map;

import org.bson.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsCriteria;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Component;

import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;

import cn.demoncat.util.lang.MapUtil;
import cn.demoncat.util.lang.StringUtil;
import cn.demoncat.util.mongo.util.QueryUtil;

/**
 * GridFs客户端
 * 
 * 1、适用于16M以上的大文件
 * 2、上传：检测MD5去重，以256K分片存储，产生两个文件fs.files（文件信息）和fs.chunks（文件分片数据）
 * 3、下载：根据文件名，找到fs.files，通过文件信息找到所有分片
 * 
 * @author 延晓磊
 *
 * @since 2017年7月22日
 */
@ConditionalOnProperty("spring.data.mongodb.grid-fs-database")
@Component
public class GridFsDao{

	/**
	 * Spring Data MongoDB GridFS
	 */
	@Autowired
	private GridFsTemplate gridFsTemplate;
	
	/**
	 * 查询文件
	 * 
	 * @param cri	查询条件：文件名、文件类型、文件元信息
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public GridFSFindIterable find(GridFsCriteria cri) {
		return this.find(Query.query(cri));
	}
	
	/**
	 * 查询文件
	 * 
	 * @param query 查询条件
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public GridFSFindIterable find(Query query){
		return gridFsTemplate.find(query);
	}
	
	/**
	 * 查询文件（单个）
	 * 
	 * @param cri	查询条件：文件名、文件类型、文件元信息
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public GridFSFile findOne(GridFsCriteria cri){
		return this.findOne(Query.query(cri));
	}
	
	/**
	 * 查询文件（单个）
	 * 
	 * @param query 查询条件
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public GridFSFile findOne(Query query){
		return gridFsTemplate.findOne(query);
	}
	
	/**
	 * 查询文件
	 * 
	 * @param id	文件ID
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020-8-31
	 */
	public GridFSFile findById(String id) {
		return findOne(QueryUtil.idQuery(id));
	}
	
	/**
	 * 删除文件
	 * 
	 * @param cri	查询条件：文件名、文件类型、文件元信息
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public void delete(GridFsCriteria cri){
		this.delete(Query.query(cri));
	}
	
	/**
	 * 删除文件
	 * 
	 * @param query 查询条件
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public void delete(Query query){
		gridFsTemplate.delete(query);
	}
	
	/**
	 * 删除文件
	 * 
	 * @param id	文件ID
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020-8-31
	 */
	public void delete(String id) {
		this.delete(QueryUtil.idQuery(id));
	}
	
	/**
	 * 上传文件 
	 * 
	 * @param in 			输入流（非空）
	 * @param fileName 		文件名（非空）
	 * @param contentType 	文件类型
	 * @param metadata 		文件元数据：文件的附加信息，可以作为查询条件
	 * 
	 * @return 文件ID
	 * 
	 * @author 延晓磊
	 *
	 * @since 2017年7月22日
	 */
	public String upload(InputStream in, String fileName, String contentType, Map<String,Object> metadata){
		return gridFsTemplate.store(in, StringUtil.checkBlank(fileName), contentType, MapUtil.isEmpty(metadata) ? null : new Document(metadata)).toString();
	}
	
	/**
	 * 下载文件
	 * 
	 * @param file	文件信息
	 * 
	 * @return 文件资源（文件信息，文件流）
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年8月31日
	 */
	public GridFsResource download(GridFSFile file) {
		return gridFsTemplate.getResource(file);
	}
	
	/**
	 * 下载文件
	 * 
	 * @param id 文件ID
	 *
	 * @return 文件资源（文件信息，文件流）
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年8月31日
	 */
	public GridFsResource download(String id){
		GridFSFile file = this.findById(id);
		return file == null ? null : this.download(file);
	}
	
}
